package com.github.chen.orm.proxy;


import com.github.chen.orm.annotation.CypherParam;
import com.github.chen.orm.annotation.CypherQuery;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

@Slf4j
public class CypherProxy<T> implements InvocationHandler {


    private Class<T> interfaceType;

    public CypherProxy(Class<T> interfaceType) {
        this.interfaceType = interfaceType;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        boolean annotationPresent = method.isAnnotationPresent(CypherQuery.class);
        if (annotationPresent) {
            //将入参整合为map
            SortedMap<Integer, String> map = paramMap(proxy, method, args);

            //获取原始查询语句
            CypherQuery cypherQuery = method.getAnnotation(CypherQuery.class);
            String queryString = cypherQuery.value();

            //对查询语句进行填充参数
            if (MapUtils.isNotEmpty(map) && map.size() == args.length) {
                queryString = fillCypherStr(args, map, queryString);
            }

            //基于neo4j引擎查询
            return "查询结果";
        }

        //未被@CypherQuery修饰的方法
        return null;
    }

    /**
     * 填充cypher查询语句
     */
    private String fillCypherStr(Object[] args, SortedMap<Integer, String> map, String queryString) {
        String cypherStr = queryString;
        log.info("cypher原始的查询语句为:{}", cypherStr);
        Iterator<Map.Entry<Integer, String>> iterator = map.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<Integer, String> entry = iterator.next();
            int key = entry.getKey();
            String value = entry.getValue();
            if (cypherStr.contains(value)) {
                cypherStr = cypherStr.replace("#{" + value + "}", "'" + args[key] + "'");
            }
        }
        if (StringUtils.isNotBlank(cypherStr)) {
            log.info("cypher填充参数后的查询语句为:{}", cypherStr);
        }
        return cypherStr;
    }

    /**
     * 按照先后顺序，构建参数Map
     */
    private SortedMap<Integer, String> paramMap(Object proxy, Method method, Object[] args) {
        final Class<?>[] paramTypes = method.getParameterTypes();
        final Annotation[][] paramAnnotations = method.getParameterAnnotations();
        final SortedMap<Integer, String> map = new TreeMap<>();
        int paramCount = paramAnnotations.length;
        for (int paramIndex = 0; paramIndex < paramCount; paramIndex++) {
            String name = null;
            for (Annotation annotation : paramAnnotations[paramIndex]) {
                if (annotation instanceof CypherParam) {
                    name = ((CypherParam) annotation).value();
                    break;
                }
            }
            map.put(paramIndex, name);
        }
        return map;
    }
}
